﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SpicIE.Controls;

namespace SpicIE.Common
{
    #region Interop definitions
    [Flags]
    [CLSCompliant(false)]
    public enum DBIM : uint
    {
        MINSIZE = 0x0001,
        MAXSIZE = 0x0002,
        INTEGRAL = 0x0004,
        ACTUAL = 0x0008,
        TITLE = 0x0010,
        MODEFLAGS = 0x0020,
        BKCOLOR = 0x0040
    }

    /// <summary>
    /// A set of flags that define the mode of operation for the band object.     
    /// </summary>
    [Flags]
    public enum DBIMF : int
    {
        NORMAL = 0x0000,
        MINSIZE = 0x0001,
        MAXSIZE = 0x0002,
        INTEGRAL = 0x0004,
        VARIABLEHEIGHT = 0x0008,
        TITLE = 0x0010,
        MODEFLAGS = 0x0020,
        BKCOLOR = 0x0040,
        USECHEVRON = 0x0080,
        BREAK = 0x0100,
        ADDTOFRONT = 0x0200,
        TOPALIGN = 0x0400,
        NOGRIPPER = 0x0800,
        ALWAYSGRIPPER = 0x1000,
        NOMARGINS = 0x2000
    }

    public struct POINT
    {
        public Int32 x;
        public Int32 y;
    }

    [ComVisible(false)]
    [CLSCompliant(false)]
    public struct MSG
    {
        public IntPtr hwnd;
        public UInt32 message;
        public UInt32 wParam;
        public Int32 lParam;
        public UInt32 time;
        public POINT pt;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public struct DESKBANDINFO
    {
        public DBIM dwMask;
        public Point ptMinSize;
        public Point ptMaxSize;
        public Point ptIntegral;
        public Point ptActual;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
        public String wszTitle;
        public DBIMF dwModeFlags;
        public Int32 crBkgnd;
    };

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public struct OLECMD
    {
        public uint cmdID;
        public uint cmdf;
    }
    #endregion

    #region Interface definitions
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IObjectWithSite
    {
        void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object site);
        void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object site);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000114-0000-0000-C000-000000000046")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IOleWindow
    {
        void GetWindow(out System.IntPtr phwnd);
        void ContextSensitiveHelp([In] bool fEnterMode);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("012dd920-7b26-11d0-8ca9-00a0c92dbfe8")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IDockingWindow
    {
        void GetWindow(out System.IntPtr phwnd);
        void ContextSensitiveHelp([In] bool fEnterMode);

        void ShowDW([In] bool fShow);
        void CloseDW([In] UInt32 dwReserved);
        void ResizeBorderDW(
            IntPtr prcBorder,
            [In, MarshalAs(UnmanagedType.IUnknown)] Object punkToolbarSite,
            bool fReserved);
    }


    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("EB0FE172-1A3A-11D0-89B3-00A0C90A90AC")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IDeskBand
    {
        void GetWindow(out System.IntPtr phwnd);
        void ContextSensitiveHelp([In] bool fEnterMode);

        void ShowDW([In] bool fShow);
        void CloseDW([In] UInt32 dwReserved);

        void ResizeBorderDW(
            IntPtr prcBorder,
            [In, MarshalAs(UnmanagedType.IUnknown)] Object punkToolbarSite,
            bool fReserved);

        void GetBandInfo(
            UInt32 dwBandID,
            UInt32 dwViewMode,
            ref DESKBANDINFO pdbi);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("68284faa-6a48-11d0-8c78-00c04fd918b4")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IInputObject
    {
        void UIActivateIO(Int32 fActivate, ref MSG msg);

        [PreserveSig]
        //[return:MarshalAs(UnmanagedType.Error)]
        Int32 HasFocusIO();

        [PreserveSig]
        Int32 TranslateAcceleratorIO(ref MSG msg);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("f1db8392-7331-11d0-8c99-00a0c92dbfe8")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IInputObjectSite
    {
        [PreserveSig]
        Int32 OnFocusChangeIS([MarshalAs(UnmanagedType.IUnknown)] Object punkObj, [MarshalAs(UnmanagedType.Bool)] bool fSetFocus);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IServiceProvider
    {
        void QueryService(
            ref Guid guid,
            ref Guid riid,
            [MarshalAs(UnmanagedType.Interface)] out Object Obj);
    }

    [ComImport, Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), InterfaceType(1)]
    [ComVisible(false)]
    [CLSCompliant(false)]
    public interface IOleCommandTarget
    {
        [PreserveSig]
        int QueryStatus([In] ref Guid pguidCmdGroup, [In] uint cCmds, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] OLECMD[] prgCmds, [In, Out] IntPtr pCmdText);
        [PreserveSig]
        int Exec([In] ref Guid pguidCmdGroup, [In] uint nCmdID, [In] uint nCmdexecopt, [In] IntPtr pvaIn, [In] IntPtr pvaOut);
    }
    #endregion

    #region Event definitions
    [ComVisible(false)]
    public delegate void ToolbarEvent_OnQuit();

    [ComVisible(false)]
    public delegate void ToolbarEvent_OnVisible(bool visible);

    [ComVisible(false)]
    public delegate void ToolbarEvent_OnExplorerAttached(EventArgs args);

    [ComVisible(false)]
    [CLSCompliant(false)]
    public delegate void ToolbarEvent_OnWindowStateChanged(uint dwWindowStateFlags, uint dwValidFlagsMask);

    [ComVisible(false)]
    public delegate void ToolbarEvent_BeforeNavigate2(object pDisp, ref object url, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel);

    [ComVisible(false)]
    public delegate void ToolbarEvent_Client2Host(ref int cx, ref int cy);

    
    [ComVisible(false)]
    public delegate void WebBrowserEvent_OnPluginLoad();

    [ComVisible(false)]
    public delegate void WebBrowserEvent_OnPluginUnLoad();

    [ComVisible(false)]
    public delegate List<IControlBase> WebBrowserEvent_OnPrepareControls();

    [ComVisible(false)]
    public delegate void WebBrowserEvent_NavigateError(
        object pDisp, ref object URL, ref object Frame, ref object StatusCode, ref bool Cancel);

    [ComVisible(false)]
    public delegate void WebBrowserEvent_NavigateComplete2(object pDisp, ref object URL);

    [ComVisible(false)]
    public delegate void WebBrowserEvent_OnQuit();

    [ComVisible(false)]
    public delegate void WebBrowserEvent_BeforeNavigate2(
        object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData,
        ref object Headers, ref bool Cancel);

    [ComVisible(false)]
    public delegate void WebBrowserEvent_DocumentComplete(object pDisp, ref object url);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_DownloadBegin();

    [ComVisible(false)]
    public delegate void WebBrowserEvents_DownloadComplete();

    [ComVisible(false)]
    public delegate void WebBrowserEvents_FullScreen(bool active);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_TheaterMode(bool active);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_TitleChange(string text);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_WindowClosing(bool IsChildWindow, ref bool Cancel);

    [ComVisible(false)]
    [CLSCompliant(false)]
    public delegate void WebBrowserEvents_WindowStateChange(uint dwWindowStateFlags, uint dwValidFlagsMask);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_FileDownload(bool ActiveDocument, ref bool Cancel);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_NewWindow2(ref object ppDisp, ref bool Cancel);

    [ComVisible(false)]
    [CLSCompliant(false)]
    public delegate void WebBrowserEvents_NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_Visible(bool visible);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_ProgressChange(int Progress, int ProgressMax);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_PropertyChange(string szProperty);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_SetPhishingFilterStatus(int PhishingFilterStatus);

    [ComVisible(false)]
    public delegate void WebBrowserEvents_UpdatePageStatus(object pDisp, ref object nPage, ref object fDone);
    #endregion

    #region Internal class definitions
    internal class Win32
    {
        public const int S_OK = 0x00000000;
        public const int S_FALSE = 0x00000001;

        public const int WM_KEYDOWN = 0x0100;
        public const int WM_KEYUP = 0x0101;
        public const int WM_USER = 0x0400;
        public const int WM_MOUSEINTERNAL = WM_USER + 10772;
        public const int WM_EXPLORERBAR_ACTIVATE = WM_USER + 10754;
        public const int WM_EXPLORERBAR_DEACTIVATE = WM_USER + 10755;
        public const int WM_SHOWBAR = WM_USER + 10756;
        public const int WM_CONNECT = WM_USER + 10757;
        public const int WM_PARENTNOTIFY = 0x0210;
        public const int WM_SETFOCUS = 0x0007;
        public const int WM_KILLFOCUS = 0x0008;
        public const int WM_NCCREATE = 0x0081;
        public const int WM_PAINT = 0x000F;
        public const int WM_COMMAND = 0x0111;
        public const int WM_WINDOWPOSCHANGED = 0x0047;
        public const int WM_SIZE = 0x0005;

        [DllImport("user32.dll")]
        public static extern IntPtr GetParent(IntPtr hwnd);

        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        [DllImport("User32.dll")]
        public static extern int PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    }

    internal class ExplorerBarWindow : System.Windows.Forms.NativeWindow, IDisposable
    {
        private bool disposed = false;
        private SpicIE.Host host;

        public ExplorerBarWindow(string caption, SpicIE.Host hostRef)
        {
            SpicIE.Host.TraceSink.TraceInformation("Toolbar: ExplorerBarWindow called (" + caption + ")");
            host = hostRef;

            CreateParams Params = new CreateParams();
            Params.Caption = caption;
            this.CreateHandle(Params);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (!this.Handle.Equals(IntPtr.Zero))
                {
                    this.DestroyHandle();
                }
            }
            disposed = true;
        }

        ~ExplorerBarWindow()
        {
            Dispose(false);
        }

        protected override void WndProc(ref Message m)
        {
            try
            {
                if (m.Msg == Win32.WM_KEYDOWN)
                {
                    int index = m.WParam.ToInt32();
                    //module.DoShortcutAction(index);
                }
                else if (m.Msg > Win32.WM_USER)
                {
                    lock (this)
                    {
                        switch (m.Msg)
                        {
                            case Win32.WM_EXPLORERBAR_ACTIVATE:
                                //module.DoIEBarActivate();
                                break;
                            case Win32.WM_EXPLORERBAR_DEACTIVATE:
                                //module.DoIEBarDeactivate();
                                break;
                            case Win32.WM_SHOWBAR:
                                //module.ShowBrowserBar(module.GetType().GUID, (m.LParam.ToInt32() == 1 ? true : false));
                                break;
                            case Win32.WM_CONNECT:
                                //module.DoConnect();
                                break;
                            case Win32.WM_MOUSEINTERNAL:
                                //module.DoMouseActivate(m.WParam.ToInt32(), m.LParam.ToInt32());
                                break;
                            default:
                                //module.DoOnSendMessage(m);
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Error in WndProc : " + ex);
            }
            finally
            {
                base.WndProc(ref m);
            }
        }
    }
    #endregion
}
